<template>
  <div
    class="img-box"
    :style="{
      backgroundImage: srcValueRef ? `url(${imgBaseUrl + srcValueRef})` : '',
      ...dropOverStyleRef,
    }"
    @dragover.prevent="handleDragOver"
    @drop.prevent="handleDrop"
  >
    <!-- 隐藏，为点击上传选择文件使用 -->
    <input
      type="file"
      @change="handleFileChange"
      ref="fileInputRef"
      style="display: none"
    />
    <input @paste="handlePaste" class="vInput" v-model="srcTextRef" />
    <span class="planeload">请再此处粘贴{{ props.placeholder }} 或 拖拽到虚线内上传{{ props.placeholder }} 或 </span>
    <el-button class="select-btn" size="small" @click="handleSelectImage"
      >点击上传{{ props.placeholder }}</el-button
    >
    <div class="btns" v-if="srcValueRef">
      <el-icon class="btn-icon" @click="delSrc"><Delete /></el-icon>
      <el-icon class="btn-icon" @click="lookSrc"><View /></el-icon>
    </div>
  </div>
  <cropperjs
    v-if="showCropperRef"
    v-model:show="showCropperRef"
    :url="imageRef"
    :extName="extNameRef"
    @clip-img="clipImg"
    v-bind="$attrs"
  />
  <el-image-viewer @close="() => { showViewerRef = false }" v-if="showViewerRef" :url-list="[imgBaseUrl + srcValueRef]" />
</template>
<script setup name="CustomUpload">
import { ref, defineProps, defineEmits , watchEffect } from 'vue';
import { ElMessage } from 'element-plus';
import { Delete, View } from '@element-plus/icons-vue';
import { uploadFileApi } from '../../apis/uploadApi';
import cropperjs from './cropperjs.vue';

const imgBaseUrl = import.meta.env.VITE_BASE_FILE_SRC;

const emits = defineEmits(['update:src']);
const props = defineProps({
  src: {
    type: String,
    default: '',
  },
  cropper: {
    type: Boolean,
    default: true,
  },
  placeholder:"封面"
});

const extNameRef = ref('');
const srcValueRef = ref('');
const srcTextRef = ref('');
const dropOverStyleRef = ref({});
const fileInputRef = ref(null);
const imageRef = ref(null);
const showCropperRef = ref(false);
const showViewerRef = ref(false);

watchEffect(() => {
  // 编辑显示图片
  if(props.src && props.src !== ''){
      srcValueRef.value = props.src;
  }
})

// 裁切确认或取消
const clipImg = (file) => {
  if (!file) return;
    uploadFun(file);
};

// 删除封面
const delSrc = () => {
    srcValueRef.value = '';
    emits('update:src', '');
};

// 查看大图
const lookSrc = () => {
    showViewerRef.value = true;
};

// 上传方法
const uploadFun = (file) => {
    uploadFileApi(file).then((res) => {
        srcValueRef.value = res;
        emits('update:src', res);
    });
};
// 校验上传图片是否符合要求
const whiteListType = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'wbmp', 'webp'];
const verifyFileIsImage = (file) => {
  if (!file) {
    ElMessage({
      message: '请上传以图片',
      type: 'warning',
    });
    return false;
  }
  const extName = file.name?.split('.')?.reverse()?.[0]?.toLowerCase();
  if (!extName && !whiteListType.includes(extName)) {
    ElMessage({
      message: '请上传以' + whiteListType.join(',') + '结尾的图片！',
      type: 'warning',
    });
    return false;
  }
    setFileExtName(extName);
    if (props.cropper) {
        imageRef.value = URL.createObjectURL(file);
        showCropperRef.value = true;
    } else {
        uploadFun(file)
    }
};

// 设置文件名称
const setFileExtName = (n) => {
  extNameRef.value = n;
};

// 粘贴内容
const handlePaste = (e) => {
  // 获取粘贴的内容
  const file = e?.clipboardData?.files?.[0] || null;
  verifyFileIsImage(file);
};

// 拖拽上传
const handleDrop = (event) => {
  event.preventDefault();
  const file = event.dataTransfer.files[0];
  verifyFileIsImage(file);
};
// 拖拽放手后，这里可以添加一些UI反馈，比如改变颜色表示可以放置
const handleDragOver = () => {
  dropOverStyleRef.value = {
    border: '1px solid var(--system-primary-color)',
  };
};

// 点击按钮-触发选择选择文件
const handleSelectImage = () => {
  fileInputRef?.value?.click(); // 触发文件选择
};
const handleFileChange = (event) => {
  const file = event.target.files[0];
  verifyFileIsImage(file);
};
</script>
<style scoped lang="less">
.img-box {
  border-radius: 15px;
  width: calc(100% - 12px);
  height: 0;
  // padding-left: 10px;
  padding-bottom: 150px;
  overflow: hidden;
  background-position: center center;
  background-repeat: no-repeat;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  background-size: cover;
  border: 1px dashed #e5e5e5;
  position: relative;
  line-height: 150px;
  position: relative;
  &::before {
    width: 100%;
    height: 100%;
    background-color: rgba(255, 255, 255, 0.5);
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    content: '';
  }
  .planeload {
    position: absolute;
    margin-top: -10px;
    top: 50%;
    left: 0;
    padding-left: 10px;
    z-index: 1;
    display: block;
    line-height: 20px;
    width: 100%;
    font-size: 13px;
    color: #333;
  }
  .select-btn {
    position: absolute;
    margin-top: -13px;
    top: 50%;
    right: 10px;
    z-index: 3;
    display: block;
    font-size: 13px;
    background-color: var(--system-primary-color);
    color: #fff;
    border-radius: 999px;
    border: none;
    cursor: pointer;
    &:hover {
      filter: brightness(0.95);
    }
  }
  .btns {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 10;
    width: 40px;
    height: 20px;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-column-gap: 4px;
    .btn-icon {
      width: 18px;
      height: 18px;
      background-color: #fff;
      border-radius: 50%;
      font-size: 12px;
      opacity: 0.6;
      cursor: pointer;
      transition: all 0.2s;
      &:hover {
        opacity: 1;
        transition: all 0.3s;
      }
    }
  }
  .vInput {
    position: absolute;
    top: 0;
    left: 5px;
    z-index: 2;
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 15px;
    background: none;
    line-height: 100px;
    color: rgba(0, 0, 0, 0);
    caret-color: #333;
  }
}
</style>
